/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.lidovky.articles.cli;

import cz.mzk.rehan.commons.DatastreamId;
import cz.mzk.lidovky.articles.PropertyNames;
import cz.mzk.lidovky.articles.articlesData.ArticleDataParser;
import cz.mzk.lidovky.articles.krameriusAccess.Repository;
import cz.mzk.rehan.commons.CommandLineInterface;
import cz.mzk.rehan.commons.PropertyLoader;
import java.io.File;
import java.lang.reflect.Constructor;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Martin Řehánek (rehan@mzk.cz)
 */
public class Main {

    private static final Logger logger = Logger.getLogger(Main.class.getName());
    private static final DefinedOptions DEFINED_OPTIONS = new DefinedOptions();

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String[] testArgs = new String[]{
            //"-p", "/home/rehan/LN_CLANKY/id1940-import.properties",
            "-p", "/home/rehan/LN_CLANKY/test.properties",
//            "-a", "import",
//            "-t",
//            "-s",
//            "-parser", "cz.mzk.lidovky.articles.articlesData.jiranova.JiranovaTsvParser"
//            "-a", "updateDatastreams",
//            "--dsId", "RELS-EXT",
//            //"--dsId", "DC",
//            "--pid-list", "/home/rehan/tmp/uuidList3.txt",
//            "--updater", "cz.mzk.lidovky.articles.updates.RelsExtModelUpdater"
        //"--updater", "cz.mzk.lidovky.articles.updates.DcTypeUpdater"
        //    "-a", "saveRepositoryErrors"
                    "-a", "restoreImportLogs"

        };
        //COMMENT THIS WHEN BUILDING PRODUCTION VERSION
        //args = testArgs;
        //COMMENT THIS WHEN BUILDING PRODUCTION VERSION
//        if (true) {
//            testMethod();
//            return;
//        }

        try {
            CommandLineInterface cli = new CommandLineInterface(args, DEFINED_OPTIONS);
            PropertyLoader properties = new PropertyLoader(cli.getStringValueOrNull(DEFINED_OPTIONS.PROPERTIES_FILE));
            Action action = determineActions(cli, properties);
            action.run();
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }
    }

    private static Action determineActions(CommandLineInterface cli, PropertyLoader properties) throws Exception {
        String action = cli.getStringValueOrNull(DEFINED_OPTIONS.ACTION);
        if ("import".equals(action)) {
            boolean test = cli.getBooleanValue(DEFINED_OPTIONS.TEST);
            boolean simplified = cli.getBooleanValue(DEFINED_OPTIONS.SIMPLIFIED);
            if (simplified) {
                properties = deriveMissingPropertiesAndCreateRequiredDirs(properties);
            }
            ArticleDataParser parser = loadParser(cli, properties);
            return new ImportArticlesAction(parser, properties, test, simplified);
        } else if ("rollback".equals(action)) {
            return new RollbackImportAction(properties);
        } else if ("reindex".equals(action)) {
            File dirList = new File(cli.getStringValueOrNull(DEFINED_OPTIONS.DIR_LIST));
            int secondsToWait = Integer.parseInt(cli.getStringValueOrNull(DEFINED_OPTIONS.SECONDS));
            return new ReindexIssuesWithArticlesAction(properties, dirList, secondsToWait);
        } else if ("printRepositoryErrors".equals(action)) {
            return new PrintRepositoryErrorsAction(properties);
        } else if ("analyzeAuthors".equals(action)) {
            ArticleDataParser parser = loadParser(cli, properties);
            return new AnalyzeAuthorsAction(parser);
        } else if ("saveRepositoryErrors".equals(action)) {
            return new SaveRepositoryErrors(properties);
        } else if ("updateDatastreams".equals(action)) {
            File pidList = new File(cli.getStringValueOrNull(DEFINED_OPTIONS.PID_LIST));
            String dsId = cli.getStringValueOrNull(DEFINED_OPTIONS.DATASTREAM_ID);
            String updaterClassName = cli.getStringValueOrNull(DEFINED_OPTIONS.UPDATER);
            return new UdateDatastreamsAction(properties, pidList, dsId, updaterClassName);
        } else if ("restoreImportLogs".equals(action)) {
            return new RestoreImportLogsAction(properties);
        } else {
            throw new Exception("no such action '" + action + "'");
        }
    }

    /**
     * Missing properties will be created (foxml dir, log dir, error file)
     * required directories will be created if needed.
     * @param loader
     * @return
     */
    private static PropertyLoader deriveMissingPropertiesAndCreateRequiredDirs(PropertyLoader loader) {
        File inputFile = loader.loadFile(PropertyNames.PARSER_INPUT_FILE, true);
        //error articles file
        String errorFileName = inputFile.getAbsolutePath() + ".error.tsv";
        loader.getProperties().setProperty(PropertyNames.PARSER_ERR_ARTICLES_FILE, errorFileName);
        System.err.println("errorFile: " + errorFileName);
        //foxmls dir
        String foxmlsDirName = inputFile.getAbsolutePath() + ".foxmls";
        createDirIfNotPresent(foxmlsDirName);
        loader.getProperties().setProperty(PropertyNames.IMPORT_FOXML_DIR, foxmlsDirName);
        //logs dir
        String logsDirName = inputFile.getAbsolutePath() + ".logs";
        loader.getProperties().setProperty(PropertyNames.IMPORT_LOG_DIR, logsDirName);
        createDirIfNotPresent(logsDirName);
        return loader;
    }

    private static void createDirIfNotPresent(String dirName) {
        File dir = new File(dirName);
        if (!dir.exists()) {
            dir.mkdir();
        }
    }

    private static ArticleDataParser loadParser(CommandLineInterface cli, PropertyLoader properties) throws Exception {
        String parserClassName = cli.getStringValueOrNull(DEFINED_OPTIONS.PARSER);
        return loadParser(parserClassName, properties);
    }

    private static ArticleDataParser loadParser(String parserClassName, PropertyLoader properties) throws Exception {
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        Class parserClass = classLoader.loadClass(parserClassName);
        Constructor[] constructors = parserClass.getConstructors();
        for (Constructor constructor : constructors) {
            if (hasAppropriateParameters(constructor)) {
                ArticleDataParser result = (ArticleDataParser) constructor.newInstance(properties.getProperties());
                return result;
            }
        }
        return null;
    }

    private static boolean hasAppropriateParameters(Constructor constructor) {
        Class[] parameterTypes = constructor.getParameterTypes();
        if (parameterTypes.length != 1) {
            return false;
        }
        Class properties = Properties.class;
        return properties.isAssignableFrom(parameterTypes[0]);
    }

    private static void testMethod() {
        try {
//            PropertyLoader properties = new PropertyLoader("/home/rehan/LN_CLANKY/test.properties");
//            String parserName = "cz.mzk.lidovky.articles.articlesData.jiranova.JiranovaTsvParser";
//            loadParser(parserName, properties);

            PropertyLoader properties = new PropertyLoader("/home/rehan/LN_CLANKY/test.properties");
            String updaterClass = "cz.mzk.lidovky.articles.updates.ModsDcTypeUpdater";
            Repository rep = Repository.instanceOf(properties);
            rep.updateArticleDatastream("uuid:86c04419-ad42-4dff-ba77-486be3eae59f", DatastreamId.DC, updaterClass);

        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
